package com.capsule.chapter.collection;


import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 工具 1.8及以上使用
 *
 * @author wulang
 * @version v1.0
 * @date 2017年11月24日 15:56
 * @description
 * @modified By:
 * @modifued reason:
 */
public class Collection7Utils {


    /**
     * 去重复和null
     *
     * @param collection 容器
     * @return java.util.List<T>
     * @author wulang
     * @date 2018/1/22 15:29
     * @modify by user: {修改人}  2018/1/22 15:29
     * @modify by reason:
     */
    public static <T> List<T> filterRepeatOrNullElement(Collection<T> collection) {
        List<T> list = Collections.emptyList();
        if (CollectionUtils.isNotEmpty(collection)) {
            list = collection.stream().filter(Objects::nonNull).distinct().collect(Collectors.toList());
        }
        return list;
    }


    /**
     * 按照指定元素属性去重，默认取第一个
     *
     * @param collection 容器
     * @return java.util.List<T>
     * @author wulang
     * @date 2018/1/22 15:29
     * @modify by user: {修改人}  2018/1/22 15:29
     * @modify by reason:
     */
    public static <T, K> List<T> filterRepeatOrNullElement(Collection<T> collection, Function<? super T, ? extends K> repeatAttr) {
        List<T> list = Collections.emptyList();
        if (CollectionUtils.isNotEmpty(collection)) {
            Set<K> filterKeySet = new HashSet<>();
            list = new ArrayList<>();
            for (T target : collection) {
                K key = repeatAttr.apply(target);
                if (!filterKeySet.contains(key)) {
                    list.add(target);
                    filterKeySet.add(key);
                }
            }
        }
        return list;
    }


    /**
     * 去除所有的空元素
     *
     * @param collection 容器
     * @return java.util.List<T>
     * @author wulang
     * @date 2018/1/22 15:29
     * @modify by user: {修改人}  2018/1/22 15:29
     * @modify by reason:
     */
    public static <T> List<T> trimNullElement(Collection<T> collection) {
        List<T> list = Collections.emptyList();
        if (CollectionUtils.isNotEmpty(collection)) {
            list = collection.stream().filter(Objects::nonNull).collect(Collectors.toList());
        }
        return list;
    }

    /**
     * 拆分链表
     *
     * @param list  目标容器
     * @param batch 批次大小
     * @return java.util.List<java.util.List<T>>
     * @author wulang
     * @date 2018/1/22 15:31
     * @modify by user: {修改人}  2018/1/22 15:31
     * @modify by reason:
     */
    public static <T> List<List<T>> splitCollection(Collection<T> list, Integer batch) {
        List<List<T>> subListCollection = Collections.emptyList();
        int startIndex = -1;
        int nextIndex = 0;
        if (CollectionUtils.isNotEmpty(list)) {
            List<T> sourceList = new ArrayList<>(list);
            int subSize = Double.valueOf(Math.ceil(1.0 * sourceList.size() / batch)).intValue();
            subListCollection = new ArrayList<>(subSize);
            for (startIndex = 0; startIndex < sourceList.size(); startIndex += batch) {
                nextIndex += batch;
                nextIndex = nextIndex > sourceList.size() ? sourceList.size() : nextIndex;
                subListCollection.add(sourceList.subList(startIndex, nextIndex));
            }
        }
        return subListCollection;
    }


    /**
     * 将容器中的数据转换成map
     *
     * @param <K>           map.entry的key的类型
     * @param <V>           map.entry的value的类型
     * @param <F>           collection中实体类型
     * @param collection    容器
     * @param valueFunction 转换规则
     * @return 返回的map永远不会为null;
     */
    public static <K, V, F> Map<K, V> transformCollectionToMap(Collection<F> collection, Function<F, K> keyFunction, Function<F, V> valueFunction) {
        Map<K, V> map = Collections.emptyMap();
        if (CollectionUtils.isNotEmpty(collection)) {
            map = new HashMap<>(collection.size());
            for (F from : collection) {
                map.put(keyFunction.apply(from), valueFunction.apply(from));
            }
        }
        return map;
    }

    /**
     * 将容器中的数据转换成map 将多个的value保存的List
     *
     * @param collection  容器
     * @param keyMapper   key
     * @param valueMapper value
     * @return java.util.Map<K,java.util.List<V>>
     * @author wulang
     * @date 2018/1/17 21:03
     * @modify by user: {修改人}  2018/1/17 21:03
     * @modify by reason:
     */
    public static <K, V, T> Map<K, List<V>> transformToMapWithListValue(Collection<T> collection,
                                                                        Function<? super T, ? extends K> keyMapper,
                                                                        Function<? super T, ? extends V> valueMapper) {
        Map<K, List<V>> map = Collections.emptyMap();
        List<V> valueList = null;
        if (CollectionUtils.isNotEmpty(collection)) {
            map = new HashMap<>();
            for (T from : collection) {
                K k = keyMapper.apply(from);
                if (CollectionUtils.isEmpty(valueList = map.get(k))) {
                    valueList = new ArrayList<>();
                }
                valueList.add(valueMapper.apply(from));
                map.put(k, valueList);
            }
        }
        return map;
    }

    /**
     * 将容器中的数据转换成map
     * 将多个的value保存到Set
     *
     * @param <K>        map.entry的key的类型
     * @param <V>        map.entry的value的类型
     * @param <F>        collection中实体类型
     * @param collection 容器
     * @return 返回的map永远不会为null;
     */
    public static <K, V, F> Map<K, Set<V>> transformToMapWithSetValue(Collection<F> collection,
                                                                      Function<? super F, ? extends K> keyMapper,
                                                                      Function<? super F, ? extends V> valueMapper) {
        Map<K, Set<V>> map = Collections.emptyMap();
        Set<V> valueSet = null;
        if (CollectionUtils.isNotEmpty(collection)) {
            Iterator<F> iterator = collection.iterator();
            map = new HashMap<>();
            while (iterator.hasNext()) {
                F from = iterator.next();
                K k = keyMapper.apply(from);
                if (CollectionUtils.isEmpty(valueSet = map.get(k))) {
                    valueSet = new HashSet<>();
                }
                valueSet.add(valueMapper.apply(from));
                map.put(k, valueSet);
            }
        }
        return map;
    }

    /**
     * 将容器中的数据转换成map
     * 将多个的value保存的Map
     * <p>
     * function 返回格式为 Map.Entry<K1, Map.Entry<K2, V>>
     *
     * @param <K1>       map.entry的key的类型
     * @param <K2>       map.entry的value的类型
     * @param <V>        map.entry的value的类型
     * @param <F>        collection中实体类型
     * @param collection 容器
     * @return 返回的map永远不会为null;
     */
    public static <K1, K2, V, F> Map<K1, Map<K2, V>> transformCollectionToMapWithMapValue(Collection<F> collection,
                                                                                          Function<? super F, ? extends K1> keyMapper1,
                                                                                          Function<? super F, ? extends K2> keyMapper2,
                                                                                          Function<? super F, ? extends V> valueMapper) {
        Map<K1, Map<K2, V>> map = Collections.emptyMap();
        if (CollectionUtils.isNotEmpty(collection)) {
            Map<K2, V> valueMap = null;
            map = new HashMap<>();
            for (F from : collection) {
                K1 k1 = keyMapper1.apply(from);
                if (MapUtils.isEmpty(valueMap = map.get(k1))) {
                    valueMap = new HashMap<>();
                }
                valueMap.put(keyMapper2.apply(from), valueMapper.apply(from));
                map.put(k1, valueMap);
            }
        }
        return map;
    }

}
